package com.dk.common.exception;


import com.dk.common.result.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException;
import java.util.stream.Collectors;


@Slf4j
@RestControllerAdvice
public class DefaultExceptionHandler {

    @Autowired
    private MultipartProperties multipartProperties;

    /**
     * 200 业务异常
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(BusinessException.class)
    public ApiResult<Void> businessException(BusinessException e) {
        log.warn("[全局异常] - 业务异常 {}", e.getMessage(), e);
        return ApiResult.fail(ApiResult.BUSINESS_FAIL_CODE, e.getMessage());
    }


    /**
     * 处理上传的文件超过指定大小的异常
     *
     * @param ex 文件大小超过指定异常
     * @return
     */
    @ExceptionHandler(value = {MaxUploadSizeExceededException.class})
    public ApiResult<Void> processFileTooLarge(MaxUploadSizeExceededException ex) {
        log.error("文件过大", ex);
        return ApiResult.fail("文件大小必须小于(" + multipartProperties.getMaxFileSize().toMegabytes() + "MB)");
    }

    /**
     * 处理字段格式校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
    public ApiResult<Void> handleValidatedException(Exception e) {
        String message = ApiResult.FAIL_MSG;
        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            message = ex.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining("; "));
        } else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException ex = (ConstraintViolationException) e;
            message = ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining("; "));
        } else if (e instanceof BindException) {
            BindException ex = (BindException) e;
            message = ex.getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining("; "));
        }
        return ApiResult.fail(message);
    }

    /**
     * 统一异常处理
     *
     * @param exception exception
     * @return
     */
    @ExceptionHandler(value = {Exception.class})
    public ApiResult<Void> processException(RuntimeException exception) {
        log.error(exception.getMessage(), exception);
        return ApiResult.fail(exception.getMessage());
    }

}



